// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010  Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.




#ifndef CL_ROSACE_H
#define CL_ROSACE_H


//////////////
// INCLUDES //
//////////////
// Misc.
#include "nel/misc/types_nl.h"
#include "nel/misc/debug.h"
// Inerface 3D.
#include "nel/3d/u_texture.h"
// Std.
#include <string>
#include <vector>
#include <map>


///////////
// USING //
///////////
using NL3D::UTextureFile;
using std::string;
using std::vector;
using std::map;


///////////
// CLASS //
///////////
/**
 * Class to manage the rosace component.
 * \author Guillaume PUZIN
 * \author Nevrax France
 * \date 2001
 */
class CRosaceComponent
{
public:
	/// Callback function for the interface controls.
	typedef void (*TFunc) (void);

protected:
	/// Position X of the component (between 0-1).
	float _X;
	/// Position Y of the component (between 0-1).
	float _Y;
	/// Width of the component (between 0-1).
	float _W;
	/// Height of the component (between 0-1).
	float _H;
	/// Callback function associated.
	TFunc _Callback;
	/// Texture used to display the component.
	UTextureFile *_Texture;

public:
	/// Constructor
	CRosaceComponent();
	/// Display the component.
	void display(bool selected);
	/// Execute the callback associated to the component.
	void execute();
	/// Set the texture for the component.
	void texture(const string &filename);
	/// Return true if the position (x,y) is inside the rosace.
	bool inside(float x, float y);
	/// Set the callback function.
	inline void callback(TFunc func) {_Callback = func;}
	/// Set the component position.
	inline void setPos(float x, float y) {_X = x; _Y = y;}
	/// Get the component position.
	inline void getPos(float &x, float &y) { x = _X; y = _Y;}
};


/**
 * Class to manage the rosace page.
 * \author Guillaume PUZIN
 * \author Nevrax France
 * \date 2001
 */
class CRosacePage
{
public:
	enum TMode
	{
		CursorMode,
		CursorAngleMode,
		RelativeMode,
		DirectMode,

		NbRosaceMode	// Not really a mode.
	};

protected:
	typedef vector<CRosaceComponent> TComponents;
	vector<CRosaceComponent> _Components;

	/// Page selected.
	sint _Selected;
	/// Old postion X.
	float _OldX;
	/// Old postion Y.
	float _OldY;
/*
	/// Component Width (between 0-1)
	float _W;
	/// Component Height (between 0-1)
	float _H;
	/// Component Width (in Pixel)
	float _W_Pixel;
	/// Component Height (in Pixel)
	float _H_Pixel;
*/

private:
	/// Select the component under the position (x,y) or unselect all if nothing at this position.
	void cursorMode(float x, float y);
	/// Select a component according to the angle generated by position (x,y) and screen center.
	void cursorAngleMode(float x, float y);
	///
	void relativeMode(float x, float y);
	///
	void directMode(float x, float y);

public:
	/// Constructor
	CRosacePage();
	CRosacePage(sint nb);
	/// Return the number of components in the page.
	inline uint size() const {return (uint)_Components.size();}
	/// Display all the components in the page.
	void display();
	/// Execute the callback associated to the selected component.
	void execute();
	/// Select the next valide component.
	void next();
	/// Select the previous valide component.
	void previous();
	/// Generate the rosace (all components).
	void generate();
	/// Update the page.
	void update(float x, float y, TMode mode);
	/// Return if the current selected component is valide.
	inline bool valide() {return (_Selected>=0 && _Selected<(sint)size());}
	///
	void select(double ang);

	/** \name Operators
	 * Operator to access to the selected component.
	 * \param comp Number of the component to access.
	 * \warning Those functions do not test if the parameter is out of range !
	 */
	//@{
	CRosaceComponent &operator [] (const uint &comp)
	{
		nlassert(comp<size());
		return _Components[comp];
	}

	const CRosaceComponent &operator [] (const uint &comp) const
	{
		nlassert(comp<size());
		return _Components[comp];
	}
	//@}
};


/**
 * Class to manage the rosace context.
 * \author Guillaume PUZIN
 * \author Nevrax France
 * \date 2001
 */
class CRosaceContext
{
protected:
	typedef vector<CRosacePage> TPages;
	vector<CRosacePage> _Pages;

	/// Page selected.
	sint _Selected;

public:
	/// Constructor
	CRosaceContext();
	CRosaceContext(sint nb);
	/// Return the number of pages in the context.
	inline uint size() const {return (uint)_Pages.size();}
	/// Display all the pages in the context.
	void display();
	/// Execute the callback associated to the selected component in the selected page.
	void execute();
	/// Add a page.
	void add(const CRosacePage &page);
	/// Update the context.
	void update(float x, float y, CRosacePage::TMode mode);
	/// Return if the current selected page is valide.
	inline bool valide() {return (_Selected>=0 && _Selected<(sint)size());}
	/// Select the next valide page.
	void next();
	/// Select the previous valide page.
	void previous();

	/** \name Operators
	 * Operator to access to the selected page.
	 * \param page Number of the page to access.
	 * \warning Those functions do not test if the parameter is out of range !
	 */
	//@{
	CRosacePage &operator [] (const uint &page)
	{
		nlassert(page<size());
		return _Pages[page];
	}

	const CRosacePage &operator [] (const uint &page) const
	{
		nlassert(page<size());
		return _Pages[page];
	}
	//@}
};


/**
 * Class to manage the rosace.
 * \author Guillaume PUZIN
 * \author Nevrax France
 * \date 2001
 */
class CRosace
{
protected:
	/// Contexts in the rosace.
	typedef map<string, CRosaceContext> TContexts;
	TContexts _Contexts;
	/// Mode to manage the rosace.
	CRosacePage::TMode _Mode;
	/// Current context.
	string _Selected;

private:
	/// Initialize the rosace.
	void init();

public:
	/// Constructor
	CRosace();
	/// Destructor.
	~CRosace();

	/// Add a page. ("" is not valide name).
	void add(const string &name, const CRosaceContext &context);
	/// Is the current context valide.
	bool valide();
	/// Select a context.
	void select(const string &name) {_Selected = name;}
	/// Change the mode.
	void mode(CRosacePage::TMode mode) {_Mode = mode;}

	/// Display the rosace.
	void display();
	/// Update the rosace.
	void update(float x, float y);
	/// Execute the callback function corresponding to the selected component.
	void execute();
	/// Swap to next rosace page.
	void swap();
};


#endif // CL_ROSACE_H

/* End of rosace.h */
